home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / segapcm.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  11KB  |  346 lines

  1. /*********************************************************/
  2. /*    SEGA 16ch 8bit PCM                                 */
  3. /*********************************************************/
  4.  
  5. #include "driver.h"
  6.  
  7. #include <math.h>
  8.  
  9. #define  PCM_NORMALIZE
  10.  
  11. #define SPCM_CENTER    (0x80)
  12. #define SEGA_SAMPLE_RATE    (15800)
  13. #define SEGA_SAMPLE_SHIFT   (5)
  14. #define SEGA_SAMPLE_RATE_OLD    (15800*2)
  15. #define SEGA_SAMPLE_SHIFT_OLD   (5)
  16.  
  17. #define  MIN_SLICE    (44/2)
  18.  
  19. #define  PCM_ADDR_SHIFT   (12)
  20.  
  21. static SEGAPCM    spcm;
  22. static int emulation_rate;
  23. static int buffer_len;
  24. static unsigned char *pcm_rom;
  25. static int  sample_rate, sample_shift;
  26.  
  27. static int stream;
  28.  
  29. static int SEGAPCM_samples[][2] = {
  30.     { SEGA_SAMPLE_RATE, SEGA_SAMPLE_SHIFT, },
  31.     { SEGA_SAMPLE_RATE_OLD, SEGA_SAMPLE_SHIFT_OLD, },
  32. };
  33.  
  34. #if 0
  35. static int segapcm_gaintable[] = {
  36.     0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
  37.     0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
  38.     0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
  39.     0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
  40.  
  41.     0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
  42.     0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
  43.     0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
  44.     0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
  45.  
  46. #if 0
  47.     0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c,0x20,0x24,0x28,0x2c,0x30,0x34,0x38,0x3c,
  48.     0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
  49.     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  50.     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
  51. #endif
  52. #if 0
  53.     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  54.     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  55.     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  56.     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  57. #endif
  58. };
  59. #endif
  60.  
  61.  
  62. static void SEGAPCMUpdate( int num, INT16 **buffer, int length );
  63.  
  64.  
  65. /************************************************/
  66. /*                                              */
  67. /************************************************/
  68. int SEGAPCM_sh_start( const struct MachineSound *msound )
  69. {
  70.     struct SEGAPCMinterface *intf = msound->sound_interface;
  71.     if (Machine->sample_rate == 0) return 0;
  72.     if( SEGAPCMInit( msound, intf->bank&0x00ffffff, intf->mode, (unsigned char *)memory_region(intf->region), intf->volume ) )
  73.         return 1;
  74.     return 0;
  75. }
  76. /************************************************/
  77. /*                                              */
  78. /************************************************/
  79. void SEGAPCM_sh_stop( void )
  80. {
  81.     SEGAPCMShutdown();
  82. }
  83. /************************************************/
  84. /*                                              */
  85. /************************************************/
  86. void SEGAPCM_sh_update( void )
  87. {
  88. }
  89.  
  90. /************************************************/
  91. /*    initial SEGAPCM                           */
  92. /************************************************/
  93. int SEGAPCMInit( const struct MachineSound *msound, int banksize, int mode, unsigned char *inpcm, int volume )
  94. {
  95.     int i;
  96.     int rate = Machine->sample_rate;
  97.     buffer_len = rate / Machine->drv->frames_per_second;
  98.     emulation_rate = buffer_len * Machine->drv->frames_per_second;
  99.     sample_rate = SEGAPCM_samples[mode][0];
  100.     sample_shift = SEGAPCM_samples[mode][1];
  101.     pcm_rom = inpcm;
  102.  
  103.     //printf( "segaPCM in\n" );
  104.  
  105.     /**** interface init ****/
  106.     spcm.bankshift = banksize&0xffffff;
  107.     if( (banksize>>16) == 0x00 )
  108.     {
  109.         spcm.bankmask = (BANK_MASK7>>16)&0x00ff;    /* default */
  110.     }
  111.     else
  112.     {
  113.         spcm.bankmask = (banksize>>16)&0x00ff;
  114.     }
  115.  
  116.     for( i = 0; i < SEGAPCM_MAX; i++ )
  117.     {
  118.         spcm.gain[i][L_PAN] = spcm.gain[i][R_PAN] = (unsigned char)0;
  119.         spcm.vol[i][L_PAN] = spcm.vol[i][R_PAN] = 0;
  120.         spcm.addr_l[i] = 0;
  121.         spcm.addr_h[i] = 0;
  122.         spcm.bank[i] = 0;
  123.         spcm.end_h[i] = 0;
  124.         spcm.delta_t[i] = 0x80;
  125.         spcm.flag[i] = 1;
  126.         spcm.add_addr[i] = 0;
  127.         spcm.step[i] = (int)(((float)sample_rate / (float)emulation_rate) * (float)(0x80<<5));
  128.         spcm.pcmd[i] = 0;
  129.     }
  130.     //printf( "segaPCM work init end\n" );
  131.  
  132.     {
  133.         char buf[LR_PAN][40];
  134.         const char *name[LR_PAN];
  135.         int  vol[2];
  136.         name[0] = buf[0];
  137.         name[1] = buf[1];
  138.         sprintf( buf[0], "%s L", sound_name(msound) );
  139.         sprintf( buf[1], "%s R", sound_name(msound) );
  140.         vol[0] = (MIXER_PAN_LEFT<<8)  | (volume&0xff);
  141.         vol[1] = (MIXER_PAN_RIGHT<<8) | (volume&0xff);
  142.         stream = stream_init_multi( LR_PAN, name, vol, rate, 0, SEGAPCMUpdate );
  143.     }
  144.     //printf( "segaPCM end\n" );
  145.     return 0;
  146. }
  147.  
  148. /************************************************/
  149. /*    shutdown SEGAPCM                          */
  150. /************************************************/
  151. void SEGAPCMShutdown( void )
  152. {
  153. }
  154.  
  155. /************************************************/
  156. /*    reset SEGAPCM                             */
  157. /************************************************/
  158. void SEGAPCMResetChip( void )
  159. {
  160.     int i;
  161.     for( i = 0; i < SEGAPCM_MAX; i++ )
  162.     {
  163.         spcm.gain[i][L_PAN] = spcm.gain[i][R_PAN] = (unsigned char)0;
  164.         spcm.vol[i][L_PAN] = spcm.vol[i][R_PAN] = 0;
  165.         spcm.addr_l[i] = 0;
  166.         spcm.addr_h[i] = 0;
  167.         spcm.bank[i] = 0;
  168.         spcm.end_h[i] = 0;
  169.         spcm.delta_t[i] = 0;
  170.         spcm.flag[i] = 1;
  171.         spcm.add_addr[i] = 0;
  172.         spcm.step[i] = (int)(((float)sample_rate / (float)emulation_rate) * (float)(0x80<<5));
  173.     }
  174. }
  175.  
  176. /************************************************/
  177. /*    update SEGAPCM                            */
  178. /************************************************/
  179.  
  180. INLINE int ILimit(int v, int max, int min) { return v > max ? max : (v < min ? min : v); }
  181.  
  182. static void SEGAPCMUpdate( int num, INT16 **buffer, int length )
  183. {
  184.     int i, j;
  185.     unsigned int addr, old_addr, end_addr, end_check_addr;
  186.     unsigned char *pcm_buf;
  187.     int  lv, rv;
  188.     INT16  *datap[2];
  189.     int tmp;
  190.  
  191.     if( Machine->sample_rate == 0 ) return;
  192.     if( pcm_rom == NULL )    return;
  193.  
  194.     datap[0] = buffer[0];
  195.     datap[1] = buffer[1];
  196.  
  197.     memset( datap[0], 0x00, length * sizeof(INT16) );
  198.     memset( datap[1], 0x00, length * sizeof(INT16) );
  199.  
  200.     for( i = 0; i < SEGAPCM_MAX; i++ )
  201.     {
  202.         if( spcm.flag[i] == 2)
  203.         {
  204.             spcm.flag[i]=0;
  205.             spcm.add_addr[i] = (( (((int)spcm.addr_h[i]<<8)&0xff00) |
  206.                   (spcm.addr_l[i]&0x00ff) ) << PCM_ADDR_SHIFT) &0x0ffff000;
  207.         }
  208.         if( !spcm.flag[i] )
  209.         {
  210.             lv = spcm.vol[i][L_PAN];   rv = spcm.vol[i][R_PAN];
  211.             if(lv==0 && rv==0) continue;
  212.  
  213.             pcm_buf = pcm_rom + (((int)spcm.bank[i]&spcm.bankmask)<<spcm.bankshift);
  214.             addr = (spcm.add_addr[i]>>PCM_ADDR_SHIFT)&0x0000ffff;
  215.             end_addr = ((((unsigned int)spcm.end_h[i]<<8)&0xff00) + 0x00ff);
  216.             if(spcm.end_h[i] < spcm.addr_h[i]) end_addr+=0x10000;
  217.  
  218.             for( j = 0; j < length; j++ )
  219.             {
  220.                 old_addr = addr;
  221.                 /**** make address ****/
  222.                 end_check_addr = (spcm.add_addr[i]>>PCM_ADDR_SHIFT);
  223.                 addr = end_check_addr&0x0000ffff;
  224.                 for(; old_addr <= addr; old_addr++ )
  225.                 {
  226.                     /**** end address check ****/
  227.                     if( end_check_addr >= end_addr )
  228.                     {
  229.                         if(spcm.writeram[i*8+0x86] & 0x02)
  230.                         {
  231.                             spcm.flag[i] = 1;
  232.                             spcm.writeram[i*8+0x86] = (spcm.writeram[i*8+0x86]&0xfe)|1;
  233.                             break;
  234.                         }
  235.                         else
  236.                         { /* Loop */
  237.                             spcm.add_addr[i] = (( (((int)spcm.addr_h[i]<<8)&0xff00) |
  238.                                     (spcm.addr_l[i]&0x00ff) ) << PCM_ADDR_SHIFT) &0x0ffff000;
  239.                         }
  240.                     }
  241. #ifdef PCM_NORMALIZE
  242.                     tmp = spcm.pcmd[i];
  243.                     spcm.pcmd[i] = (int)(*(pcm_buf + old_addr) - SPCM_CENTER);
  244.                     spcm.pcma[i] = (tmp - spcm.pcmd[i]) / 2;
  245.                     spcm.pcmd[i] += spcm.pcma[i];
  246. #endif
  247.                 }
  248.                 spcm.add_addr[i] += spcm.step[i];
  249.                 if( spcm.flag[i] == 1 )  break;
  250. #ifndef PCM_NORMALIZE
  251.                 *(datap[0] + j) = ILimit( (int)*(datap[0] + j) + ((int)(*(pcm_buf + addr) - SPCM_CENTER)*lv), 32767, -32768 );
  252.                 *(datap[1] + j) = ILimit( (int)*(datap[1] + j) + ((int)(*(pcm_buf + addr) - SPCM_CENTER)*rv), 32767, -32768 );
  253. #else
  254.                 *(datap[0] + j) = ILimit( (int)*(datap[0] + j) + (spcm.pcmd[i] * lv), 32767, -32768 );
  255.                 *(datap[1] + j) = ILimit( (int)*(datap[1] + j) + (spcm.pcmd[i] * rv), 32767, -32768 );
  256. #endif
  257.             }
  258.             /**** end of length ****/
  259.         }
  260.         /**** end flag check ****/
  261.     }
  262.     /**** pcm channel end ****/
  263.  
  264. }
  265.  
  266. /************************************************/
  267. /*    wrtie register SEGAPCM                    */
  268. /************************************************/
  269. WRITE_HANDLER( SegaPCM_w )
  270. {
  271.     int r = offset;
  272.     int v = data;
  273.     int rate;
  274.     int  lv, rv, cen;
  275.  
  276.     int channel = (r>>3)&0x0f;
  277.  
  278.     spcm.writeram[r&0x07ff] = (char)v;        /* write value data */
  279.     switch( (r&0x87) )
  280.     {
  281.         case 0x00:
  282.         case 0x01:
  283.         case 0x84:  case 0x85:
  284.         case 0x87:
  285.             break;
  286.  
  287.         case 0x02:
  288.             spcm.gain[channel][L_PAN] = v&0xff;
  289. remake_vol:
  290.             lv = spcm.gain[channel][L_PAN];   rv = spcm.gain[channel][R_PAN];
  291.             cen = (lv + rv) / 4;
  292. //            spcm.vol[channel][L_PAN] = (lv + cen)<<1;
  293. //            spcm.vol[channel][R_PAN] = (rv + cen)<<1;
  294.             spcm.vol[channel][L_PAN] = (lv + cen)*9/5;    // too much clipping
  295.             spcm.vol[channel][R_PAN] = (rv + cen)*9/5;
  296.             break;
  297.         case 0x03:
  298.             spcm.gain[channel][R_PAN] = v&0xff;
  299.             goto remake_vol;
  300.  
  301.  
  302.         case 0x04:
  303.             spcm.addr_l[channel]= v;
  304.             break;
  305.         case 0x05:
  306.             spcm.addr_h[channel]= v;
  307.             break;
  308.         case 0x06:
  309.             spcm.end_h[channel]= v;
  310.             break;
  311.         case 0x07:
  312.             spcm.delta_t[channel]= v;
  313.             rate = (v&0x00ff)<<sample_shift;
  314.             spcm.step[channel] = (int)(((float)sample_rate / (float)emulation_rate) * (float)rate);
  315.             break;
  316.         case 0x86:
  317.             spcm.bank[channel]= v;
  318.             if( v&1 )    spcm.flag[channel] = 1; /* stop D/A */
  319.             else
  320.             {
  321.                 /**** start D/A ****/
  322. //                spcm.flag[channel] = 0;
  323.                 spcm.flag[channel] = 2;
  324. //                spcm.add_addr[channel] = (( (((int)spcm.addr_h[channel]<<8)&0xff00) |
  325. //                      (spcm.addr_l[channel]&0x00ff) ) << PCM_ADDR_SHIFT) &0x0ffff000;
  326.                 spcm.pcmd[channel] = 0;
  327.             }
  328.             break;
  329.         /*
  330.         default:
  331.             printf( "unknown %d = %02x : %02x\n", channel, r, v );
  332.             break;
  333.         */
  334.     }
  335. }
  336.  
  337. /************************************************/
  338. /*    read register SEGAPCM                     */
  339. /************************************************/
  340. READ_HANDLER( SegaPCM_r )
  341. {
  342.     return spcm.writeram[offset & 0x07ff];        /* read value data */
  343. }
  344.  
  345. /**************** end of file ****************/
  346.